<?php


namespace app\logic\recharge;


use app\utils\Helper;
use coco\Exception;
use coco\Log;
use coco\Request;
use coco\Response;

class Shuzi extends Base implements Template
{

    public static function info(): array
    {
        return [
            'support_type' => 1,//支持类型
            'name' => '数字',
            'cfg' => [
                //name 名称 required是否必填(默认必填) allow_edit种植期间是否允许修改(默认不允许)
                'mch_id' => ['name' => '商户号'],
                'key' => ['name' => '签名密钥', 'required' => false],
                'admin_url' => ['name' => '后台地址', 'allow_edit' => true],
                'api_url' => ['name' => '网关', 'allow_edit' => true],
                'ip_white_lists' => ['name' => '回调白名单', 'placeholder' => '多个逗号分割,不填表示不限制', 'allow_edit' => true, 'required' => false],  
                
                'productids' => ['name' => '产品编号', 'placeholder' => '多个逗号分割,格式yd50:30000005154,yd100:30000005155', 'allow_edit' => true, 'required' => false],                
            ],
        ];
    }
    /**
     * @param array $param
     * @return array|false
     * 返回false表示明确失败  订单会处理为失败状态
     * 其他表示成功或者未知 未知情况需要手动确认 或者定时查询
     * 时间间隔不一定 自行处理
     */
    public function submit(array $param)
    {
        $types = ['', 'yd', 'lt', 'dx'];
        try{
            $productids = array_column(array_map(function($v){
                list($i_p,$productid)=explode(':',$v);
                if(empty($productid))
                {
                    throw new Exception('`产品编号`配置出错');
                }
                $isp=substr($i_p,0,2);
                if(!in_array($isp,['yd','lt','dx']))
                {
                    throw new Exception('`产品编号`配置出错');
                }
                $price=substr($i_p,2);
                $key=$isp.'_'.$price;
                return compact('key','productid');
            },explode(',',$this->cfg['productids'])),'productid','key');
        }catch(\Exception $e)
        {
            $this->error = $e->getMessage();
            return false;
        }
        if(empty($productids[$types[$param['order']['ext2']].'_'.$param['price']]))
        {
            $this->error = '不支持的产品';
            return false;
        }

        $productid = $productids[$types[$param['order']['ext2']].'_'.$param['price']];
        $params = [
            "userid" => $this->cfg['mch_id'],
            "sporderid" => $param['trade_no'],
            "mobile" => $param['order']['uuid'],
            "price" => $param['price'],
            "num"=>1,
            'paytype' => $types[$param['order']['ext2']],
            'spordertime'=>date('YmdHis'),
            'back_url' => $this->getNotifyUrl($param['platfrom_id']),
            'productid'=> $productid,
        ];
        $before =
            'userid=' . $params['userid'] . '&' .
            'productid=' . $params['productid'] . '&' .
            'price=' . $params['price'] . '&' .
            'num=' . $params['num'] . '&' .
            'mobile=' . $params['mobile'] . '&' .
            'spordertime=' . $params['spordertime'] . '&' .
            'sporderid=' . $params['sporderid'] . '&' .
            'key=' . $this->cfg['key'];
        $params["sign"] = md5($before);
        $headers = array(
            "Content-Type:application/x-www-form-urlencoded;charset=utf-8",
        );
        $data = http_build_query($params);
        $url = $this->cfg['api_url'] . '/onlinepay.do';
        $log = [];
        $log['url'] = $url;
        $log['data'] = $data;
        $result = Helper::http_post($url, $data, $headers, 30);
        if (false === $result) {
            $log['response'] = 'curl fail';
            return ['is_confirm' => 1, 'log' => $log];
        }
        $ret = (array)simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA);
        $log['response'] = json_encode($ret,JSON_UNESCAPED_UNICODE);//编码问题 这里记录json 不记录原始串
        if (empty($ret)  || !array_key_exists('orderid', $ret)) {
            $log['decode'] = '服务器响应错误';
            return ['is_confirm' => 1, 'log' => $log];
        }
        $log['decode'] = json_encode($ret,JSON_UNESCAPED_UNICODE);
        if ($ret['resultno'] != '0' && $result['resultno'] != '2') {
            $this->error = '错误码:' . $ret['resultno'];
            return false;
        }
        return ['log' => $log, 'out_trade_no' => $ret['orderid']];
    }

    public function notify(Request $request, string $ip)
    {
        if (!empty($this->cfg['ip_white_lists'])) {
            $ip_white_lists = explode(',', $this->cfg['ip_white_lists']);
            if (!in_array($ip, $ip_white_lists)) {
                $this->error = '非法请求';
                return false;
            }
        }
        
        $param = $request->post();
        $before =
            'userid=' . $param['userid'] . '&' .
            'orderid=' . $param['orderid'] . '&' .
            'sporderid=' . $param['sporderid'] . '&' .
            'merchantsubmittime=' . $param['merchantsubmittime'] . '&' .
            'resultno=' . $param['resultno'] . '&' .
            'key=' . $this->cfg['key'];
        if ($param['sign'] != strtoupper(md5($before))) {
            $this->error = '签名错误';
            return false;
        }
        
        $status = $param["resultno"];
        $success = [1,];
        $fail = [9,];
        $ignore = [];
        if (in_array($status, $success)) {
            $voucher = $param['remark1'];
            $ret = 'success';
        } elseif (in_array($status, $fail)) {
            $msg = '渠道充值失败';
            $ret = 'fail';
        } elseif (in_array($status, $ignore)) {
            $ret = 'ignore';
        } else {
            throw new Exception('错误的状态');
        }
        $out_trade_no = $param['sporderid'];
        return ['ret' => $ret, 'msg' => $msg ?? '', 'trade_no' => $out_trade_no, 'voucher' => $voucher??''];
    }

    public function notifyResponse(): Response
    {
        $response = new Response(['type' => 'txt']);
        $response->setData(['txt' => 'OK']);
        return $response;
    }

    /**
     * @param array $param subimit 表内容
     * @param int $act 0 普通查询 1 成功查询 2确认查询
     * @return false|mixed|string
     */
    public function query(array $param, int $act = 0)
    {
        $params = [
            "userid" => $this->cfg['mch_id'],
            "sporderid" => $param['trade_no'],
        ];
        $before =
            'userid=' . $param['userid'] . '&' .
            'sporderid=' . $param['sporderid'] . '&' .
            'key=' . $this->cfg['key'];
        $params['sign']=strtoupper(md5($before));
        $headers = array(
            "Content-Type:application/x-www-form-urlencoded;charset=utf-8",
        );
        $data = http_build_query($params);
        $url = $this->cfg['api_url'] . '/searchpay.do';
        if (false === $result = Helper::http_post($url, $data, $headers, 30)) {
            $this->error = 'curl fail';
            return false;
        }
        $log['response'] = $result;
        $ret = (array)simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA);
        if (empty($ret)  || !array_key_exists('orderid', $ret)) {
            $this->error = '服务器响应错误';
            return false;
        }
        $log['decode'] = json_encode($ret,JSON_UNESCAPED_UNICODE);

//         1	充值成功	订单成功
// 9	充值失败已退款	订单失败
// 5007	所查询的订单不存在	异常,下单10分钟后查询结果为5007可处理为失败
// 其他结果	其他状态	充值中,不处理
        
        if ($act === 1) {
            if ($ret['resultno'] == 1) {
                return ['ret' => 'success', 'voucher' => $ret['remark1'] ?? ''];
            } elseif ($ret['resultno'] === 9) {
                return ['ret' => 'fail'];
            } else {
                return ['ret' => 'other'];
            }
        } elseif ($act === 2) {
            if ($ret['resultno'] == '5007') {
                return 'no';
            }
            return 'yes';
        }
        return $ret;
    }
}